from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn import metrics, svm
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
import tensorflow as tf
from tensorflow import keras
import pandas as pd
import matplotlib.pyplot as plt
import json
from tensorflow.keras.utils import plot_model

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'


# 在服务上跑的数据是20201226日生成的data
# 服务器的path的内容
# path = "../rawdata2020122602.csv"

path = "D:/learn/school/code/myfinalpaper/data/rawdata2020122602.csv"

df = pd.read_csv(path)
x = df['data']
y = df['label']


def do_metrics(y_test_truth, y_test_pred):
    print("metrics.accuracy_score:")
    print(metrics.accuracy_score(y_test_truth, y_test_pred))
    print("metrics.confusion_matrix:")
    print(metrics.confusion_matrix(y_test_truth, y_test_pred))
    print("metrics.precision_score:")
    print(metrics.precision_score(y_test_truth, y_test_pred))
    print("metrics.recall_score:")
    print(metrics.recall_score(y_test_truth, y_test_pred))
    print("metrics.f1_score:")
    print(metrics.f1_score(y_test_truth, y_test_pred))
    TN = metrics.confusion_matrix(y_test_truth, y_test_pred)[0, 0]
    FP = metrics.confusion_matrix(y_test_truth, y_test_pred)[0, 1]
    FN = metrics.confusion_matrix(y_test_truth, y_test_pred)[1, 0]
    TP = metrics.confusion_matrix(y_test_truth, y_test_pred)[1, 1]
    print("TN: " + str(TN))
    print("FP: " + str(FP))
    print("FN: " + str(FN))
    print("TP: " + str(TP))
    print("真正率TPR: " + str(TP/(TP+FN)))
    print("假正率FPR漏报率: " + str(FP/(FP+TN)))
    print("假负率FNR误报率: " + str(FN/(TP+FN)))
    print("真负率TNR: " + str(TN/(TN+FP)))

def model_prediction(model, name, x_test, y_test):
    y_predict_list = model.predict(x_test)
    y_predict = []
    for i in y_predict_list:
        if i[0] > 0.5:
            y_predict.append(0)
        else:
            y_predict.append(1)
    y_test_truth = y_test[:, 1]
    do_metrics(y_test_truth, y_predict)
    dataframe = pd.DataFrame({'y_test_truth': y_test_truth,
                              'y_predict_score': y_predict_list[:, 1],  # 这个才是最终的内容，不要再修改其中的值了
                              'y_predict_label': y_predict})
    dataframe.to_csv("./BiGRU/" + name + '.csv', sep=',', index=False)

def w2c_bigru(x, y, opcodelength):
    # os.mkdir("w2c_bigru")
    print("*****************************************")
    modelname = str(opcodelength) + "-bigru"
    print("用" + modelname + "模型预测")
    tokenizer = keras.preprocessing.text.Tokenizer(
        filters='!"#$%&()*+,-./:;<=>?@[\\]^`{|}~\t\n')  # 创建一个Token，用来讲文本的词汇转回为索引数字
    # tokenizer = keras.preprocessing.text.Tokenizer()
    tokenizer.fit_on_texts(x)
    # vocab = tokenizer.word_index  # 得到每个词的编号

    x_id = tokenizer.texts_to_sequences(x)

    x = keras.preprocessing.sequence.pad_sequences(x_id, maxlen=opcodelength, padding='post', truncating='post')

    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

    y_train_class = tf.keras.utils.to_categorical(y_train, num_classes=2)

    y_test_class = tf.keras.utils.to_categorical(y_test, num_classes=2)

    model = keras.Sequential([
        keras.layers.Embedding(20480, 128),
        keras.layers.Bidirectional(tf.keras.layers.GRU(128)),
        keras.layers.Dropout(0.2),
        keras.layers.Dense(2, activation="softmax")
    ])
    # 获取模型结构
    # plot_model(model, show_shapes=True, show_layer_names=True)

    model.compile(loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                  optimizer=tf.keras.optimizers.Adam(0.001),
                  metrics=['accuracy'])
    #获取 词嵌入层 数据内容
    embeddings = model.layers[0].get_weights()[0]
    model.fit(x_train,
              y_train_class,
              epochs=10,
              validation_data=(x_test, y_test_class),
              batch_size=32,
              shuffle=True
              )

    model_prediction(model, modelname, x_test, y_test_class)
    tf.saved_model.save(model, "./BiGRU/" + modelname + "saved/1")
    print("用" + modelname +"模型预测结束")
    print("*****************************************")

if __name__ == "__main__":
    os.mkdir("BiGRU")
    w2c_bigru(x, y, 50)
    w2c_bigru(x, y, 100)
    w2c_bigru(x, y, 200)
    w2c_bigru(x, y, 300)
    w2c_bigru(x, y, 400)
    w2c_bigru(x, y, 500)
    w2c_bigru(x, y, 600)

